package com.hsxc.cdz.mgmt.pile;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import com.hsxc.cdz.base.bean.Reserv;
import com.hsxc.cdz.monitor.FSM.PileMemStateReserved;
import com.hsxc.cdz.monitor.executor.ServerExecutor;
import com.hsxc.cdz.trans.bill.CacheTrade;
import org.omg.IOP.ENCODING_CDR_ENCAPS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hsxc.cdz.base.bean.Pile;
import com.hsxc.cdz.base.util.ApplicationUtil;
import com.hsxc.cdz.mgmt.GlobalManager;
import com.hsxc.cdz.monitor.FSM.CachePile;
import com.hsxc.cdz.monitor.FSM.PileMemState.Status;

import io.netty.channel.ChannelHandlerContext;

public class CachePileManager {
    // Logger
    private static Logger logger = LoggerFactory.getLogger(CachePileManager.class);

    //public PileManager pileRegister = (PileManager) ApplicationUtil.getBean("pileManager");
    // 缓存所有充电桩内存对象
    private Map<String, CachePile> pileMap = new ConcurrentHashMap<>(1024);
    /****************************************/
    public static final int SUCCESS = 0;
    public static final int FAILURE = 1;

    // 创建新的内存对象并加入哈希链表
    public int newPile(CachePile pile) {
        if (pile != null) {
            System.out.println("内存中加入了一个pile,pile address 是" + pile.getAddress());
            pileMap.put(pile.getAddress(), pile);
            System.out.println(pileMap.size());
            return SUCCESS;
        }
        return FAILURE;

    }

    // Pile对象从Hash链表删除并销毁
    /*
     * 0 成功
	 */
    public int delPile(String address) {
        return pileMap.remove(address) == null ? FAILURE : SUCCESS;

    }

    // 根据key值从链表中获取cachePile对象
    public CachePile getPile(String address) {
        if (address != null) {
            return pileMap.get(address);
        }
        return null;
    }

    //获取所有缓存的电桩
    public List<CachePile> getAllCachePile() {
        List<CachePile> cachePiles = new ArrayList<>();
        for (Map.Entry<String, CachePile> entry : pileMap.entrySet()) {
            if (entry.getValue() != null) {
                cachePiles.add(entry.getValue());
            }
        }
        return cachePiles;
    }

    // 根据key值从链表中获取cachePile对象
    public CachePile getPile(ChannelHandlerContext ctx) {
        if (ctx == null) {
            return null;
        }
        for (Entry<String, CachePile> entry : pileMap.entrySet()) {
            if (entry.getValue().getChannel() == ctx.channel()) {
                return entry.getValue();
            }
        }
        return null;
    }

    // 判断链表中是否存在相同的key
    public boolean containPile(String key) {
        return pileMap.get(key) != null;
    }

    public boolean removeChannel(ChannelHandlerContext ctx) {
        if (ctx == null) {
            return false;
        }
        for (Entry<String, CachePile> entry : pileMap.entrySet()) {
            if (entry.getValue().getChannel() == ctx.channel()) {
                entry.getValue().state.offLine();
                pileMap.remove(entry.getKey());
                //应该更新数据库电桩的信息
                Pile pile = new Pile();
                pile.setPileNO(entry.getKey());
                pile.setState(Pile.STATE_OFFLINE);
                GlobalManager.pileRegister.updatePile(pile);
                return true;
            }
        }
        return false;
    }

    /**
     * 注册充电桩
     *
     * @param pile 充电桩数据
     * @param ctx  连接通道的信息
     * @return true 注册成功，false 内存中已存在该桩
     */
    public boolean registerPile(Pile pile, ChannelHandlerContext ctx, String protocolVersion) {
        // 判断内存中是否存在该桩，存在即为重名
        CachePile cachePile = GlobalManager.pileManager.getPile(pile.getPileNO());
        /*
         * if (cachePile == null ||
		 * cachePile.getChannel().equals(ctx.channel())) { cachePile = new
		 * CachePile(pile.getOperatorNO(), pile.getPileNO());
		 * cachePile.setChannel(ctx.channel());
		 * cachePile.setStation(pile.getStationNO());
		 * cachePile.setOperator(pile.getOperatorNO());
		 * GlobalManager.pileManager.newPile(cachePile);
		 * pileRegister.login(pile); return true; } return false;
		 */
        cachePile = new CachePile(pile.getOperatorNO(), pile.getPileNO());
        cachePile.setChannel(ctx.channel());
        cachePile.setStation(pile.getStationNO());
        cachePile.setOperator(pile.getOperatorNO());
        cachePile.setProtocolVersion(protocolVersion);
        cachePile.setPileType(pile.getPhyType());
        GlobalManager.pileManager.newPile(cachePile);
        GlobalManager.pileRegister.login(pile);
        return true;
    }

    public boolean loadPile(Pile pile, ChannelHandlerContext ctx, String protocolVersion, int pileType) {
        //CachePile cachePile = GlobalManager.pileManager.getPile(pile.getPileNO());
		/*
		 * if (cachePile == null ||
		 * cachePile.getChannel().equals(ctx.channel())) { cachePile = new
		 * CachePile(pile.getOperatorNO(), pile.getPileNO());
		 * cachePile.setChannel(ctx.channel());
		 * cachePile.setOperator(pile.getOperatorNO());
		 * cachePile.setStation(pile.getStationNO());
		 * GlobalManager.pileManager.newPile(cachePile);
		 * pileRegister.login(pile); return true; } return false;
		 */
        CachePile cachePile = new CachePile(pile.getOperatorNO(), pile.getPileNO());
        Reserv reserv = GlobalManager.cacheReservManager.queryReservByPileNo(pile.getPileNO());
        if (reserv != null) {
            logger.info("电桩登录时，存在预约，直接恢复预约状态");
            cachePile.changeStateReserv();
            //ServerExecutor.reserve(reserv.getChargePort(),reserv.getUserNo(),reserv.getPileNo(),reserv.getOperatorNo(),reserv.getDuration(),protocolVersion,pileType);
        }
        CacheTrade cacheTrade = GlobalManager.tradeManager.getPayTrade(pile.getPileNO());
        //cachePile = cacheTrade.getCachePile();
        if (cacheTrade == null) {
            //没有该桩的交易为正常登陆
            logger.info("电桩登录时，不存在交易，正常登录");

        } else if (cacheTrade.getTradeStatus() == CacheTrade.TradeStatus.TRADE_STATUS_READY) {
            cachePile = cacheTrade.getCachePile();
            cachePile.changeStateLocked();
        } else if (cacheTrade.getTradeStatus() == CacheTrade.TradeStatus.Trade_STATUS_FAIL) {
            cachePile = cacheTrade.getCachePile();
            cachePile.changeStateLocked();
        } else if (cacheTrade.getTradeStatus() == CacheTrade.TradeStatus.TRADE_STATUS_NOPAY) {
            ;
        } else if (cacheTrade.getTradeStatus() == CacheTrade.TradeStatus.TRADE_STATUS_ON) {
            cachePile = cacheTrade.getCachePile();
            cachePile.changeStateCharge();
        }
        cachePile.setChannel(ctx.channel());
        cachePile.setStation(pile.getStationNO());
        cachePile.setOperator(pile.getOperatorNO());
        cachePile.setProtocolVersion(protocolVersion);
        cachePile.setPileType(pile.getPhyType());
        GlobalManager.pileManager.newPile(cachePile);
        GlobalManager.pileRegister.login(pile);
        return true;
    }

    public void logoutAll() {
        if (pileMap != null) {
            for (Entry<String, CachePile> entry : pileMap.entrySet()) {
                entry.getValue().logout();
            }
        }
    }

    public List<CachePile> getCachePileByStationNo(String stationNo) {
        List<CachePile> cachePiles = new ArrayList<>();
        Iterator<Map.Entry<String, CachePile>> entries = pileMap.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, CachePile> entry = entries.next();
            CachePile cachePile = entry.getValue();
            if (cachePile != null) {
                if (cachePile.getStation().equals(stationNo)) {
                    cachePiles.add(cachePile);
                }
            }
        }
        return cachePiles;
    }

    public List<CachePile> getIdleCachePileByStationNo(String stationNo) {
        List<CachePile> idleCachePiles = new ArrayList<>();
        Iterator<Map.Entry<String, CachePile>> iterator = pileMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, CachePile> entry = iterator.next();
            CachePile cachePile = entry.getValue();
            if (cachePile != null && cachePile.getStation().equals(stationNo)
                    && cachePile.getStatus() == Status.PILE_STATUS_IDLE) {
                idleCachePiles.add(cachePile);
            }
        }
        return idleCachePiles;
    }

    public void dumpPileInfo() {
        Iterator<Map.Entry<String, CachePile>> iter = pileMap.entrySet().iterator();
        int i = 0;
        while (iter.hasNext()) {
            CachePile pile = iter.next().getValue();
            if (null != pile) {
                logger.debug("Pile no: {}", pile.getAddress());
                i++;
            } else {
                logger.debug("Pile is NULL!");
            }
        }
        logger.debug("Total {} piles.", i);
    }
}

